package com.zslibrary.serialport;

import android.util.Log;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SerialPort {

    private static final String TAG = "SerialPort";

    /*
     * Do not remove or rename the field mFd: it is used by native method close();
     */
    private FileDescriptor mFd;
    private FileInputStream mFileInputStream;
    private FileOutputStream mFileOutputStream;

    private String mDeviceName;
    private int mBaudrate;

    public SerialPort() {
    }

    public SerialPort(String deviceName, int baudrate) {
        mDeviceName = deviceName;
        mBaudrate = baudrate;
    }

    public String getDeviceName() {
        return mDeviceName;
    }

    public void setDeviceName(String deviceName) {
        mDeviceName = deviceName;
    }

    public int getBaudrate() {
        return mBaudrate;
    }

    public void setBaudrate(int baudrate) {
        mBaudrate = baudrate;
    }

    public void reopen() throws SecurityException, IOException {
        this.closePort();
        openPort(mDeviceName, mBaudrate);
    }

    public void openPort(String deviceName, int baudrate) throws SecurityException, IOException {

        mDeviceName = deviceName;
        mBaudrate = baudrate;

        File file = new File(mDeviceName);
        /* Check access permission */
        if (!file.canRead() || !file.canWrite()) {
            try {
                /* Missing read/write permission, trying to chmod the file */
                Process su;
                su = Runtime.getRuntime().exec("/system/xbin/su");
                String cmd = "chmod 666 " + file.getAbsolutePath() + "\n"
                        + "exit\n";
                su.getOutputStream().write(cmd.getBytes());
                if ((su.waitFor() != 0) || !file.canRead()
                        || !file.canWrite()) {
                    throw new SecurityException();
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new SecurityException();
            }
        }

        mFd = open(file.getAbsolutePath(), mBaudrate);
        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

    public void closePort() {
        try {
            if (mFd != null) {
                this.close();
                mFileInputStream.close();
                mFileOutputStream.close();
                mFd = null;
                mFileInputStream = null;
                mFileOutputStream = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Getters and setters
    public InputStream getInputStream() {
        return mFileInputStream;
    }

    public OutputStream getOutputStream() {
        return mFileOutputStream;
    }

    // JNI
    private native FileDescriptor open(String path, int baudrate);

    private native int close();

    static {
        System.loadLibrary("SerialPort");
    }

}